# -*- coding: utf-8 -*-
# gui.py
# 这是一个GUI类，用于创建和布局控件，以及处理一些界面相关的事件
# 导入PyQt5等模块
import socket
import os
import html
import platform

from PyQt5 import QtCore
from PyQt5.QtWidgets import (
    QApplication,
    QWidget,
    QGridLayout,
    QLabel,
    QLineEdit,
    QPushButton,
    QFileDialog,
    QProgressBar,
    QMessageBox,
    QListWidget,
    QListWidgetItem,
    QStyle,
    QSizePolicy,
    QMenuBar,
    QMenu,
    QDialog,
    QTextEdit,
    QVBoxLayout,
    QInputDialog,
    QSplitter,
    QFrame,
    QToolButton,
    QHBoxLayout,
    QStatusBar,
    QMainWindow
)
from PyQt5.QtCore import Qt, pyqtSignal as Signal, QSize
from PyQt5.QtGui import QTextCursor, QFont
from PyQt5.QtWidgets import QAction  # PyQt5中QAction属于QtWidgets模块

# 导入自定义模块（需确保这些模块也已转换为PyQt5版本）
from user_input import UserInput
from info_dialog import InfoDialog

# 定义Changelog常量
CHANGELOG = """
版本 1.0.0
- 实现了基本的FTP协议功能，包括ls, cd, get, put, quit
- 使用PySide6创建了一个图形化界面，可以显示当前目录和文件列表，可以上传和下载文件，可以切换目录
- 使用QProgressBar显示了传输进度
- 使用QListWidget优化了文件列表的显示，可以双击文件或目录进行操作
- 增加了Changelog的功能，可以查看版本更新的信息

版本 1.1.0
- 在文件列表中存储文件大小，并提供文件菜单选项，方便用户查看
- 为发送和接收文件的方法增加异常处理机制，并在传输结束后显示相关信息
- 支持restart命令，可以根据需要自动或手动地设置和清除断点
- 在必要的时机及时清除客户端相关数据，避免对后续操作造成影响
- 实现文件的断点续传功能，通过QPushButton控件，将中断和重连的操作集成到一个按钮上
- 完善对各控件的控制逻辑，避免用户在传输过程中进行错误或冲突的操作
- 修复若干bug

版本 1.1.1
- 客户端在完整接收数据后再进行解码，防止多字节字符因被截断而导致解码错误
- 将GUI部分的代码封装为一个独立的文件gui.py，实现代码的清晰性和模块化
- 将选择文件的操作委托给GUI类，使客户端类与PySide6模块解耦
- 将主函数的代码拆分为main.py文件，使client.py文件仅负责FTP客户端的逻辑
- 在传输完成后及时同步删除断点，防止对后续传输造成干扰

版本 2.0.0
- 重建用户界面
  - 主窗口改为由QMainWindow类派生，并使用多层窗口部件和不同类型的布局（垂直、水平、网格）来构建界面
  - 删除冗余的控件和属性配置，精简代码逻辑
  - 通过引入菜单栏、状态栏、分割器等组件，优化了界面布局的效果和美感
  - 添加命令行界面，定义用户输入文本框类，支持快捷发送、多行输入和在主窗口保持响应的同时按顺序执行
  - 创建控制台界面，将之前在控制台输出的信息以富文本形式呈现在文本框控件里
  - 用一个实时更新的标签来显示清空进度，替代原来的单行覆盖输出
  - 将原有的ChangelogDialog类重构为一个通用的InfoDialog类，增加一个title参数，用于展示不同主题的信息对话框
  - 将gui.py文件中的一些自定义控件类分离出来，并各自保存在单独的文件中
  - 按照代码结构的逻辑，把布局或功能相近的控件代码分组排列，增强代码的可读性
- 调整部分控件的启用/禁用状态的逻辑，以兼容全新UI下findChildren方法的变化（详见GUI类的set_enabled方法的注释）
- 在窗口关闭按钮的点击事件中，执行发送quit命令的方法，以保证在窗口关闭前，与服务器正确地断开连接
- 修改若干bug
- 待实现：登录功能

版本 2.1.0
- 设计并实现用户的登录和注册模块
  - 支持login和register命令，可以验证或创建用户的身份信息，以便访问FTP服务器
  - 利用PySide6构建登录窗口，实现与服务器的连接和登录或注册的请求发送，嵌入一个注册窗口，提供更多的功能选项
  - 为登录窗口添加一个方法，用于处理窗口关闭事件，以保证在与服务器建立连接的情况下，能够正确地释放资源
  - 利用sqlite3模块，在服务器端建立和管理一个数据库文件，用于保存用户的用户名和密码信息
  - 增加了对用户名和密码的约束
"""

# 定义帮助常量
HELP = """
本文档是FTP客户端的使用指南，介绍了它的主要功能和操作步骤：
- 左侧文件列表显示当前目录的内容，双击文件夹可进入，双击文件可下载，双击返回项可回到上级目录。右键单击文件，即可弹出菜单，显示文件的大小
- 右上控制台呈现FTP客户端的输出，如命令结果，传输信息，错误提示等
- 右下输入框可输入FTP命令，如ls, cd, get, put等。Ctrl+Enter换行，Enter或发送按钮执行。发送按钮菜单可选Enter或Ctrl+Enter发送模式
- 状态栏位于窗口的底部，用一个进度条展示文件传输的百分比。另外一个标签显示取消下载后释放缓冲区的状态。一个按钮可以切换传输的暂停或继续
- 菜单栏提供了菜单选项，点击后可弹出Changelog或帮助对话框，分别展示程序的更新日志和功能说明
"""

# 定义图标映射常量（PyQt5与PySide6的QStyle常量一致）
ICONS = {
    'play': QStyle.SP_MediaPlay,
    'pause': QStyle.SP_MediaPause,
    'stop': QStyle.SP_MediaStop,
    'next': QStyle.SP_MediaSkipForward,
    'previous': QStyle.SP_MediaSkipBackward
}

class FTPClientGUI(QMainWindow):
    # 信号定义（PyQt5使用pyqtSignal装饰器，这里直接使用Signal别名）
    progress_signal = Signal(int)
    icon_signal = Signal(str)
    file_dialog_signal = Signal(str)
    error_signal = Signal(str)
    result = Signal(bool)
    clear_signal = Signal(int)
    output_signal = Signal(str)
    output_signal2 = Signal(str)
    server_info_signal = Signal(str)

    def __init__(self):
        super().__init__()

    def create_ui(self, ftp_client):
        self.setWindowTitle("FTP客户端")
        self.setWindowIcon(self.style().standardIcon(QStyle.SP_ComputerIcon))
        self.resize(1000, 600)
        self.center()
        self.ftp_client = ftp_client
        self.index = 0
        self.commands = []
        self.clear_percent = 0
        self.server_info = ''

        self.menu_bar = self.menuBar()
        self.menu_bar.setNativeMenuBar(False)
        self.menu = QMenu("菜单")
        self.changelog_action = self.menu.addAction("Changelog", self.show_changelog)
        self.help_action = self.menu.addAction("帮助", self.show_help)
        self.menu_bar.addMenu(self.menu)
        self.changelog_action.setMenuRole(QAction.MenuRole.ApplicationSpecificRole)
        self.help_action.setMenuRole(QAction.MenuRole.ApplicationSpecificRole)

        self.dir_label = QLabel("当前目录：")
        self.dir_edit = QLineEdit()
        self.dir_button = QPushButton("切换")
        self.upload_button = QPushButton("上传")
        self.quit_button = QPushButton("退出")
        self.file_label = QLabel("文件列表：")
        self.file_list = QListWidget()
        self.file_list.setSelectionMode(QListWidget.SingleSelection)
        self.break_button = QPushButton("设置断点")
        self.clear_button = QPushButton("清除断点")
        self.progress_label = QLabel("传输进度：")
        self.progress_bar = QProgressBar()
        self.connect_button = QPushButton()
        self.connect_button.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
        self.clear_console_button = QPushButton("清空")
        self.init_button = QPushButton("初始化")
        self.output_label = QLabel("控制台：")
        self.output_edit = QTextEdit()
        self.output_edit.setReadOnly(True)
        self.output_edit.setAcceptRichText(True)
        self.output_edit.setFont(QFont("Microsoft Yahei", 11))
        self.input_label = QLabel("在此输入命令：")
        self.send_mode = "Enter"
        self.input_edit = UserInput(self)
        self.input_edit.setFont(QFont("Microsoft Yahei", 11))
        self.send_button = QToolButton()
        self.send_button.setText("发送")
        self.send_button.setPopupMode(QToolButton.MenuButtonPopup)
        self.send_menu = QMenu()
        self.send_enter_action = self.send_menu.addAction("Press Enter to send", lambda: self.set_send_mode("Enter"))
        self.send_enter_action.setCheckable(True)
        self.send_ctrl_enter_action = self.send_menu.addAction("Press Ctrl+Enter to send", lambda: self.set_send_mode("Ctrl+Enter"))
        self.send_ctrl_enter_action.setCheckable(True)
        self.send_button.setMenu(self.send_menu)
        self.send_enter_action.setChecked(True)
        self.send_button.clicked.connect(self.send_button_clicked)

        self.left_layout = QVBoxLayout()
        self.left_layout.addWidget(self.file_label)
        self.left_layout.addWidget(self.file_list)
        self.left_buttons_layout = QGridLayout()
        self.left_buttons_layout.addWidget(self.break_button, 0, 0)
        self.left_buttons_layout.addWidget(self.clear_button, 0, 1)
        self.left_layout.addLayout(self.left_buttons_layout)
        self.left_layout_widget = QWidget()
        self.left_layout_widget.setContentsMargins(0, 0, 0, 0)
        self.left_layout_widget.setLayout(self.left_layout)

        self.v_splitter = QSplitter(Qt.Vertical)
        self.v_splitter.setHandleWidth(10)
        self.v_splitter.setChildrenCollapsible(False)

        self.upper_half = QWidget()
        self.upper_half_layout = QVBoxLayout()
        self.upper_half_buttons = QHBoxLayout()
        self.upper_half_buttons.addWidget(self.output_label)
        self.upper_half_buttons.addStretch()
        self.upper_half_buttons.addWidget(self.quit_button)
        self.upper_half_buttons.addWidget(self.init_button)
        self.upper_half_buttons.addWidget(self.clear_console_button)
        self.upper_half_layout.addLayout(self.upper_half_buttons)
        self.upper_half_layout.addWidget(self.output_edit)
        self.upper_half.setLayout(self.upper_half_layout)

        self.bottom_half = QWidget()
        self.bottom_half_layout = QVBoxLayout()
        self.bottom_half_buttons = QHBoxLayout()
        self.bottom_half_buttons.addWidget(self.input_label)
        self.bottom_half_buttons.addStretch()
        self.bottom_half_buttons.addWidget(self.upload_button)
        self.bottom_half_buttons.addWidget(self.send_button)
        self.bottom_half_layout.addLayout(self.bottom_half_buttons)
        self.bottom_half_layout.addWidget(self.input_edit)

        self.clear_label = QLabel("清空进度：0%")
        self.status_bar = QStatusBar()
        self.status_bar.addWidget(self.clear_label)
        self.status_bar.addWidget(self.progress_bar, 1)
        self.status_bar.addPermanentWidget(self.connect_button)
        self.bottom_half_layout.addWidget(self.status_bar)
        self.bottom_half.setLayout(self.bottom_half_layout)

        self.v_splitter.addWidget(self.upper_half)
        self.v_splitter.addWidget(self.bottom_half)
        self.v_splitter.setStretchFactor(0, 3)
        self.v_splitter.setStretchFactor(1, 1)
        self.v_splitter.setSizes([460, 140])

        self.user_label = QLabel()
        self.server_label = QLabel()
        self.dir_layout = QHBoxLayout()
        self.dir_layout.addWidget(self.dir_label)
        self.dir_layout.addWidget(self.dir_edit)
        self.dir_layout.addWidget(self.dir_button)
        self.dir_layout.addStretch()
        self.dir_layout.addWidget(self.user_label)
        self.dir_layout.addWidget(self.server_label)
        self.dir_layout.setContentsMargins(8, 0, 8, 0)

        self.main_layout = QHBoxLayout()
        self.main_layout.addWidget(self.left_layout_widget, 1)
        self.main_layout.addWidget(self.v_splitter, 6)
        self.main_layout.setContentsMargins(0, 0, 0, 0)

        self.frame_layout = QVBoxLayout()
        self.frame_layout.setContentsMargins(0, 0, 0, 0)
        self.frame_layout.addLayout(self.dir_layout)
        self.frame_layout.addLayout(self.main_layout)

        self.frame_widget = QWidget()
        self.frame_widget.setLayout(self.frame_layout)
        self.setCentralWidget(self.frame_widget)

        self.menu_bar.setFixedHeight(25)
        self.menu_bar.setFixedWidth(200)
        self.dir_button.setFixedWidth(80)
        self.dir_label.setFixedWidth(80)
        self.break_button.setFixedSize(80, 25)
        self.clear_button.setFixedSize(80, 25)
        self.send_button.setFixedSize(80, 25)
        self.clear_console_button.setFixedSize(80, 25)
        self.input_label.setFixedHeight(25)
        self.output_label.setFixedHeight(25)
        self.file_label.setFixedHeight(25)

        self.dir_button.clicked.connect(ftp_client.change_dir)
        self.upload_button.clicked.connect(ftp_client.upload_file)
        self.quit_button.clicked.connect(ftp_client.quit)
        self.clear_console_button.clicked.connect(self.output_edit.clear)
        self.connect_button.clicked.connect(self.toggle_connect)
        self.break_button.clicked.connect(self.set_breakpoint)
        self.clear_button.clicked.connect(ftp_client.clear_breakpoint)
        self.init_button.clicked.connect(self.init_data)

        self.progress_signal.connect(self.progress_bar.setValue)
        self.file_dialog_signal.connect(self.show_file_dialog)
        self.error_signal.connect(self.show_error)
        self.icon_signal.connect(self.change_icon)
        self.result.connect(self.handle_result)
        self.clear_signal.connect(self.update_clear_label)
        self.output_signal2.connect(self.write_output_put, type=QtCore.Qt.UniqueConnection)
        self.output_signal.connect(self.write_output)
        self.server_info_signal.connect(self.change_server_info)

        self.file_list.itemDoubleClicked.connect(self.double_click_file)
        self.file_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.file_list.customContextMenuRequested.connect(self.show_menu)

    def set_user_and_server(self, username, server_info):
        self.user_label.setText(f"<font color='blue'>欢迎，{username}</font>")
        self.server_label.setText(f"<font color='green'>你已连接到：{server_info}</font>")
        self.server_info = server_info

    def set_send_mode(self, key):
        if key == "Enter":
            self.send_mode = "Enter"
            self.send_enter_action.setChecked(True)
            self.send_ctrl_enter_action.setChecked(False)
        else:
            self.send_mode = "Ctrl+Enter"
            self.send_enter_action.setChecked(False)
            self.send_ctrl_enter_action.setChecked(True)

    def send_button_clicked(self):
        command = self.input_edit.toPlainText().strip()
        if command:
            self.commands = command.split("\n")
            self.index = 0
            self.input_edit.clear()
            self.execute_command()

    def execute_command(self):
        if self.index < len(self.commands):
            cmd = self.commands[self.index]
            self.ftp_client.send_command(cmd)
        else:
            self.index = 0
            self.commands = []

    def handle_result(self, result):
        if result:
            self.index += 1
            self.execute_command()
        else:
            remaining_commands = self.commands[self.index + 1:]
            if remaining_commands:
                remaining_commands_str = ", ".join(remaining_commands)
                self.output_edit.append(f"由于上一条命令执行失败，以下命令将不会执行：{remaining_commands_str}")
            self.index = 0
            self.commands = []

    def closeEvent(self, event):
        self.ftp_client.send_command("quit")
        super().closeEvent(event)

    def update_dir_and_file(self, response):
        parts = response.split("\n", 1)
        if len(parts) >= 2:
            dir, file = parts
        else:
            dir = response
            file = ""
        
        # 处理以"OK"开头的目录响应（来自cd命令的成功响应）
        if dir.startswith("OK "):
            dir = dir[3:]  # 移除"OK "前缀
        
        # 添加调试信息和验证
        if not dir or dir.isdigit():
            # 如果目录为空或者是数字，使用默认目录
            dir = "C:\\" if platform.system() == "Windows" else "/"
            # 发送cd命令回到根目录
            self.ftp_client.send_command('cd')
        
        self.ftp_client.current_dir = dir
        self.dir_edit.setText(self.ftp_client.current_dir)
        self.file_list.clear()
        back_item = QListWidgetItem('..')
        back_item.setIcon(self.style().standardIcon(QStyle.SP_ArrowBack))
        back_item.setData(Qt.UserRole, 'back')
        self.file_list.insertItem(0, back_item)
        files = file.split('\n')
        dirs = []
        file_items = []
        for file_entry in files:
            # 跳过空的文件条目
            if not file_entry.strip():
                continue
            if self.ftp_client.current_dir == '\\':
                item = QListWidgetItem(file_entry)
                item.setIcon(self.style().standardIcon(QStyle.SP_DriveHDIcon))
                item.setData(Qt.UserRole, 'drive')
                dirs.append(item)
            elif file_entry.endswith('\\'):
                item = QListWidgetItem(file_entry.rstrip('\\'))
                item.setIcon(self.style().standardIcon(QStyle.SP_DirIcon))
                item.setData(Qt.UserRole, 'directory')
                dirs.append(item)
            else:
                try:
                    parts = file_entry.split(' ', 1)
                    if len(parts) >= 2:
                        size, filename = parts
                        size = int(size)
                        item = QListWidgetItem(filename)
                        item.setIcon(self.style().standardIcon(QStyle.SP_FileIcon))
                        item.setData(Qt.UserRole, 'file')
                        item.setData(Qt.UserRole + 1, size)
                        file_items.append(item)
                    else:
                        # 如果没有空格分隔，将整个条目作为文件名，大小设为0
                        item = QListWidgetItem(file_entry)
                        item.setIcon(self.style().standardIcon(QStyle.SP_FileIcon))
                        item.setData(Qt.UserRole, 'file')
                        item.setData(Qt.UserRole + 1, 0)
                        file_items.append(item)
                except:
                    pass
        items = dirs + file_items
        for item in items:
            self.file_list.addItem(item)

    def update_dir_and_file2(self, response):
        parts = response.split("\n", 1)
        if len(parts) >= 2:
            dir, file = parts
        else:
            dir = response
            file = ""
        
        # 处理以"OK"开头的目录响应（来自cd命令的成功响应）
        if dir.startswith("OK "):
            dir = dir[3:]  # 移除"OK "前缀
        
        # 添加调试信息和验证
        if not dir or dir.isdigit():
            # 如果目录为空或者是数字，使用默认目录
            dir = "C:\\" if platform.system() == "Windows" else "/"
            # 发送cd命令回到根目录
            self.ftp_client.send_command('cd')
        
        self.ftp_client.current_dir = dir
        self.dir_edit.setText(self.ftp_client.current_dir)
        self.file_list.clear()
        back_item = QListWidgetItem('..')
        back_item.setIcon(self.style().standardIcon(QStyle.SP_ArrowBack))
        back_item.setData(Qt.UserRole, 'back')
        self.file_list.insertItem(0, back_item)
        files = file.split('\n')
        dirs = []
        file_items = []
        for file_entry in files:
            # 跳过空的文件条目
            if not file_entry.strip():
                continue
            if self.ftp_client.current_dir == '/':
                item = QListWidgetItem(file_entry)
                item.setIcon(self.style().standardIcon(QStyle.SP_DriveHDIcon))
                item.setData(Qt.UserRole, 'drive')
                dirs.append(item)
            elif file_entry.endswith('/'):
                item = QListWidgetItem(file_entry.rstrip('/'))
                item.setIcon(self.style().standardIcon(QStyle.SP_DirIcon))
                item.setData(Qt.UserRole, 'directory')
                dirs.append(item)
            else:
                try:
                    parts = file_entry.split(' ', 1)
                    if len(parts) >= 2:
                        size, filename = parts
                        size = int(size)
                        item = QListWidgetItem(filename)
                        item.setIcon(self.style().standardIcon(QStyle.SP_FileIcon))
                        item.setData(Qt.UserRole, 'file')
                        item.setData(Qt.UserRole + 1, size)
                        file_items.append(item)
                    else:
                        # 如果没有空格分隔，将整个条目作为文件名，大小设为0
                        item = QListWidgetItem(file_entry)
                        item.setIcon(self.style().standardIcon(QStyle.SP_FileIcon))
                        item.setData(Qt.UserRole, 'file')
                        item.setData(Qt.UserRole + 1, 0)
                        file_items.append(item)
                except:
                    pass
        items = dirs + file_items
        for item in items:
            self.file_list.addItem(item)

    def set_enabled(self, enabled):
        self.dir_label.setEnabled(enabled)
        self.dir_edit.setEnabled(enabled)
        self.dir_button.setEnabled(enabled)
        self.file_label.setEnabled(enabled)
        self.file_list.setEnabled(enabled)
        self.break_button.setEnabled(enabled)
        self.clear_button.setEnabled(enabled)
        self.quit_button.setEnabled(enabled)
        self.init_button.setEnabled(enabled)
        self.clear_console_button.setEnabled(enabled)
        self.connect_button.setEnabled(enabled)
        self.upload_button.setEnabled(enabled)
        self.send_button.setEnabled(enabled)
        self.progress_label.setEnabled(enabled)
        self.progress_bar.setEnabled(enabled)

    def select_file(self):
        filename, _ = QFileDialog.getOpenFileName(self, "选择文件", ".", "所有文件 (*)")
        return filename

    def update_clear_label(self, percent):
        self.clear_label.setText(f"清空进度：{percent}%")

    def show_file_dialog(self, filename):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        filename, _ = QFileDialog.getSaveFileName(
            self, "保存文件", filename, "所有文件 (*)", options=options
        )
        if filename:
            self.ftp_client.file_queue.put(filename)
        else:
            self.ftp_client.file_queue.put("")

    def show_error(self, error):
        msg_box = QMessageBox()
        msg_box.setWindowTitle("错误")
        msg_box.setIcon(QMessageBox.Critical)
        msg_box.setText(error)
        msg_box.setStandardButtons(QMessageBox.Ok)
        msg_box.exec_()

    def double_click_file(self, item):
        item_type = item.data(Qt.UserRole)
        if item_type == "back":
            self.ftp_client.send_command("cd ..")
        elif item_type == "directory" or item_type == "drive":
            self.ftp_client.send_command("cd " + item.text())
        elif item_type == "file":
            self.ftp_client.send_command("get " + item.text())

    def change_icon(self, icon_name):
        icon = ICONS.get(icon_name, QStyle.SP_DialogApplyButton)
        self.connect_button.setIcon(self.style().standardIcon(icon))

    def set_breakpoint(self):
        if self.ftp_client.filesize > 0:
            msg_box = QMessageBox()
            msg_box.setWindowTitle('设置断点')
            msg_box.setIcon(QMessageBox.Question)
            msg_box.setText('是否要自动获取断点？')
            msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            choice = msg_box.exec_()
            if choice == QMessageBox.Yes:
                if self.ftp_client.sent > 0:
                    base_filename = os.path.basename(self.ftp_client.filename)
                    items = self.file_list.findItems(base_filename, Qt.MatchExactly)
                    if items:
                        item = items[0]
                        breakpoint = item.data(Qt.UserRole + 1)
                        self.ftp_client.send_command("restart " + str(breakpoint))
                    else:
                        self.write_output(f"<font color='orange' face='underline'>没有找到文件名为{base_filename}的列表项目</font>")
                elif self.ftp_client.received > 0:
                    self.ftp_client.send_command("restart " + str(os.path.getsize(self.ftp_client.download_filename)))
            else:
                breakpoint, ok = QInputDialog.getInt(self, '设置断点', '请输入断点的位置（字节）：')
                if ok and breakpoint > 0:
                    self.ftp_client.send_command("restart " + str(breakpoint))
                else:
                    self.write_output("取消设置断点")
        else:
            breakpoint, ok = QInputDialog.getInt(self, '设置断点', '请输入断点的位置（字节）：')
            if ok and breakpoint > 0:
                self.ftp_client.send_command("restart " + str(breakpoint))
            else:
                self.write_output("取消设置断点")

    def toggle_connect(self):
        if self.ftp_client.filesize > 0:
            if not self.ftp_client.stopped:
                self.ftp_client.sock.close()
            else:
                self.ftp_client.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.ftp_client.connect_server()
                msg_box = QMessageBox()
                msg_box.setWindowTitle('续传文件')
                msg_box.setIcon(QMessageBox.Question)
                msg_box.setText('是否要续传文件？')
                msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
                choice = msg_box.exec_()
                if choice == QMessageBox.Yes:
                    self.set_breakpoint()
                    if self.ftp_client.sent > 0:
                        self.ftp_client.send_command("put " + self.ftp_client.filename)
                    elif self.ftp_client.received > 0:
                        self.ftp_client.send_command("get " + self.ftp_client.filename)
                self.ftp_client.stopped = False
                self.connect_button.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
                self.change_server_info(f"你已连接到：{self.server_info}")
        else:
            self.show_error("没有正在传输的文件")

    def init_data(self):
        msg_box = QMessageBox()
        msg_box.setWindowTitle('初始化')
        msg_box.setIcon(QMessageBox.Question)
        msg_box.setText('你确定要初始化所有数据吗？这将删除所有的客户端数据。')
        msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        msg_box.setDefaultButton(QMessageBox.No)
        reply = msg_box.exec_()
        if reply == QMessageBox.Yes:
            self.ftp_client.init_data()
        else:
            self.write_output("取消初始化")

    def show_changelog(self):
        self.changelog_dialog = InfoDialog("Changelog", CHANGELOG, self)
        self.changelog_dialog.show()

    def show_help(self):
        self.help_dialog = InfoDialog("帮助", HELP, self)
        self.help_dialog.show()

    def show_menu(self, pos):
        item = self.file_list.itemAt(pos)
        if item and item.data(Qt.UserRole) == 'file':
            menu = QMenu()
            size_action = menu.addAction('文件大小')
            size_action.triggered.connect(lambda: self.show_size(item))
            menu.exec_(self.file_list.mapToGlobal(pos))

    def show_size(self, item):
        size = item.data(Qt.UserRole + 1)
        msg_box = QMessageBox()
        msg_box.setWindowTitle('文件大小')
        msg_box.setIcon(QMessageBox.Information)
        msg_box.setText(f'{item.text()}的大小为{size}字节')
        msg_box.setStandardButtons(QMessageBox.Ok)
        msg_box.exec_()

    def write_output_put(self,text):
        print(f"out for this:{text}")
        self.output_edit.append(str(text))
        self.output_edit.moveCursor(QTextCursor.End)

    def write_output(self, text):
        if platform.system() == "Windows":
            self.output_edit.append(text)
            self.output_edit.moveCursor(QTextCursor.End)
        elif platform.system() == "Linux":
            self.output_signal2.emit(str(text))

    def change_server_info(self, server_info):
        self.server_label.setText(f"<font color='green'>{server_info}</font>")

    def center(self):
        qr = self.frameGeometry()
        screen = QApplication.primaryScreen()
        cp = screen.availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
